﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MP3Ganizer.Common.Interfaces.FileTree;
using Microsoft.Practices.Unity;
using MP3Ganizer.Common.BaseObject;
using MP3Ganizer.BusinessObject.Hierarchy;
using System.Collections.ObjectModel;
using System.Threading;
using MP3Ganizer.BusinessObject.Services.Classification;
using MP3Ganizer.BusinessObject.Services.IO;
using System.Windows;
using System.Windows.Threading;
using MP3Ganizer.BusinessObject.Infos;
using System.Collections;
using Microsoft.Practices.Composite.Presentation.Commands;
using MP3Ganizer.BusinessObject.Services.Configuration;
using System.ComponentModel;
using MP3Ganizer.Controls.Message;
using MP3Ganizer.Modules.FileTree.Views;
using MP3Ganizer.BusinessObject.DataToPersist;
using MP3Ganizer.BusinessObject.Services.Common;
using Microsoft.Practices.Composite.Events;
using MP3Ganizer.Events.User;
using MP3Ganizer.Common;
using System.Windows.Data;

namespace MP3Ganizer.Modules.FileTree.ViewModels
{
    public class FileTreeViewModel : ModuleViewModelBase, IFileTreeViewModel
    {
        private IUnityContainer _unityContainer;
        private IClassificationService _classificationService;
        private IFileService _fileService;
        private List<MP3Infos> _infos;
        private ObservableCollection<IFileItemViewModel> _fileViewItems;

        public ObservableCollection<IFileItemViewModel> FileViewItems
        {
            get { return _fileViewItems; }
            set
            {
                _fileViewItems = value;
                OnPropertyChanged("FileViewItems");
            }
        }
        private DelegateCommand<object> _classifyByAlbumCommand;
        private DelegateCommand<object> _classifyByArtistsCommand;
        private DelegateCommand<object> _classifyByDirectoryCommand;
        private IConfigurationService _configurationService;
        private ObservableCollection<IHierarchy> _list;
        private int _viewStyle;
        private string _directory;
        private IEventAggregator _eventAggregator;
        private IServiceResult _result;
        public ObservableCollection<IHierarchy> List
        {
            get
            {
                return _list;
            }
            set
            {
                _list = value;
                OnPropertyChanged("List");

            }
        }

        private void AdaptViewFromStyle()
        {
            switch (_viewStyle)
            {
                case (int)ViewModels.ViewStyle.Albums:
                    {
                        ClassifyByAlbum();
                        break;
                    }
                case (int)ViewModels.ViewStyle.Artists:
                    {
                        ClassifyByArtist();
                        break;
                    }
                case (int)ViewModels.ViewStyle.Folders:
                    {
                        ClassifyByDirectory();
                        break;
                    }
            }
        }

        public int ViewStyle
        {
            get
            {
                AdaptViewFromStyle();
                return _viewStyle;
            }
            set
            {
                _viewStyle = value;
                OnPropertyChanged("ViewStyle");
            }
        }

        public DelegateCommand<object> ClassifyByAlbumCommand
        {
            get
            {
                return _classifyByAlbumCommand;
            }
        }

        public DelegateCommand<object> ClassifyByArtistsCommand
        {
            get
            {
                return _classifyByArtistsCommand;
            }
        }

        public DelegateCommand<object> ClassifyByDirectoryCommand
        {
            get
            {
                return _classifyByDirectoryCommand;
            }
        }

        public FileTreeViewModel(IUnityContainer unityContainer)
        {
            _unityContainer = unityContainer;
            _eventAggregator = _unityContainer.Resolve<IEventAggregator>();
            _classificationService = _unityContainer.Resolve<IClassificationService>();
            _fileService = _unityContainer.Resolve<IFileService>();
            _configurationService = _unityContainer.Resolve<IConfigurationService>();
            _list = new ObservableCollection<IHierarchy>();
            _infos = new List<MP3Infos>();
            _classifyByAlbumCommand = new DelegateCommand<object>(ClassifyByAlbumAction);
            _classifyByArtistsCommand = new DelegateCommand<object>(ClassifyByArtistAction);
            _classifyByDirectoryCommand = new DelegateCommand<object>(ClassifyByDirectoryAction);
            _fileViewItems = new ObservableCollection<IFileItemViewModel>();
        }

        public void SetDirectory(string directory)
        {
            _directory = directory;
        }

        protected override void OnLoad()
        {
            _list.Clear();
            _infos.Clear();
            _fileViewItems.Clear();
            _result = _fileService.GetMP3InfosFromDirectory(_directory, _infos);
            if (_result is ServiceSuccess)
                ClassifyByArtist();
            _configurationService.PersistConfig();

        }

        protected override void OnloadCompleted()
        {
            foreach (var info in _infos)
            {
                _list.Add(new FileModel(info.Title, info));
                _configurationService.SetInfo(InfoType.Albums, info.Album);
                IEnumerable<OverridableData> results;
                if (_configurationService.GetInfos<OverridableData>(InfoType.ArtistsEntireList, out results))
                {
                    var oldArtist = results.FirstOrDefault(item => info.Artists.Contains(item.OldName));
                    if (oldArtist != null)
                    {
                        info.Artists = info.Artists.Where(item => !item.Equals(oldArtist.OldName));
                        if (!info.Artists.Contains(oldArtist.OverridenName))
                            info.Artists = info.Artists.Concat(new string[] { oldArtist.OverridenName });
                    }
                }
                info.Artists.ToList().ForEach(artist => _configurationService.SetInfo(InfoType.Artists, artist));
                _infos.Add(info);
                IFileItemViewModel itemViewModel = _unityContainer.Resolve<IFileItemViewModel>();
                itemViewModel.SetInfo(info);
                itemViewModel.Initialize();
                _fileViewItems.Add(itemViewModel);
            }
            _eventAggregator.GetEvent<UserActionEvent>().Publish(new UserActionEventArgs(Enums.UserAction.LoadedFileTree));
        }

        private void ClassifyByArtistAction(object o)
        {
            ClassifyByArtist();
        }
        private void ClassifyByArtist()
        {
            _list.Clear();
            _classificationService.ClassifyByArtists(_infos).Select(item => (IHierarchy)item).ToList().ForEach(i => _list.Add(i));
        }
        private void ClassifyByAlbumAction(object o)
        {
            ClassifyByAlbum();
        }
        private void ClassifyByAlbum()
        {
            _list.Clear();
            _classificationService.ClassifyByAlbum(_infos).Select(item => (IHierarchy)item).ToList().ForEach(i => _list.Add(i));
        }
        private void ClassifyByDirectoryAction(object o)
        {
        }
        private void ClassifyByDirectory()
        {
            _list.Clear();
            _classificationService.ClassifyByDirectory(_infos).Select(item => (IHierarchy)item).ToList().ForEach(i => _list.Add(i));
        }

        public void Reload()
        {
            Initialize();
        }
    }

    internal enum ViewStyle
    {
        Artists = 0,
        Albums = 1,
        Folders = 2,
        List = 3
    }
}
